;(function( scope ){
		   
var Benchmark = scope.Benchmark = function( tests ){
	// store the argument { name: test }
	this.tests = tests;
	// store the times and iterations
	this.results = [];
	// store the last returned values
	this.returns = {};
	};
Benchmark.prototype = {
	// execute each test a number of times
	run: function( iterations, args ){
		// hold the results of this run
		var run = { iterations:iterations };
		// each test
		this.each(function( name, test ){
			// start timing			   
			var start = ( new Date() ).getTime(), i, end, result;
			// repeat iterations
			for ( i = 0; i < iterations; i++ ){
				// call the test function
				result = test.apply( this, args || [] );
				}
			// stop timing	
			end = ( new Date() ).getTime();
			// store the results of this test
			run[ name ] = {
				start: start,
				end: end,
				time: ( end - start ),
				result: result
				}; 
			});
		// store the results of all tests
		this.results.push( run );
		},
	// iterate each named test	
	each: function( func ){
		for ( var name in this.tests ){
			func.call( this, name, this.tests[ name ] );
			}
		},
	// output the results in an html table
	getReport: function(){
		var i, run, total = { iterations:0 }, ctrl, time,
		// start the table...
		html = ['<table cellpadding="0" cellspacing="0">'];
		// ...the head section
		html.push('<thead>');
		html.push('<tr><td>Run</td><td>Iterations</td>');
		this.each(function( name ){
			total[ name ] = 0;			   
			html.push('<td>', name, '</td>');			   
			});  
		html.push('</tr>');
		html.push('</thead>');
		// ...the body section
		html.push('<tbody>');
		for ( i = 0; i < this.results.length; i++ ){
			run = this.results[ i ];
			html.push('<tr><td>', i + 1, '</td><td>', run.iterations, '</td>');
			total.iterations += run.iterations;
			this.each(function( name ){
				time = run[ name ].time;
				ctrl = ctrl || time;
				html.push('<td class="', ( ctrl > time ? "green" : ctrl < time ? "red" : "" ),'">', time ,'</td>');
				total[ name ] += time;
				});
			ctrl = null;
			html.push('</tr>');
			}
		html.push('</tbody>');	
		// ...the foot sections
		html.push('<tfoot>');
		html.push('<tr><td>Totals</td><td>', total.iterations ,'</td>');
		this.each(function( name ){
			html.push('<td>', total[ name ] ,'</td>');
			});
		html.push('</tr>');
		html.push('<tr><td>Percent</td><td>', total.iterations ,'</td>');
		this.each(function( name ){
			ctrl = ctrl || total[ name ];
			html.push('<td>',
				Math.round( total[ name ] / ctrl * 100 ), 
				'%</td>');
			});
		html.push('</tr>');
		html.push('</tfoot>');
		html.push('</table>');
		return html.join("");
		},
	// return the test return values at given index
	getResults: function( i ){
		if ( i == undefined ) // use last run
			i = this.results.length - 1;
		var results = [];
		this.each(function( name ){
			results.push({
				name: name,
				result: this.results[ i ][ name ].result
				});
			});
		return results;
		}
	};

})( window );